[Bubblewrap/LXC/WSLC] Add filesystem-policy delegation check#598
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a cross-backend “filesystem-policy delegation” gate so Linux (LXC/Bubblewrap) and WSLC runs reject readonlyPaths/readwritePaths entries that the invoking user cannot access, preventing the sandbox from being granted more filesystem access than the caller has.
Changes:
- Introduces
wxc_common::filesystem_accesswith a per-platform access probe (access(2)/CreateFileW) andcheck_delegation(ContainerPolicy). - Wires the delegation check into Bubblewrap, LXC, and WSLC runners close to mount/enforcement.
- Adds unit tests for common allow/skip/reject cases.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/core/wxc_common/src/lib.rs | Exposes the new filesystem_access module from wxc_common. |
| src/core/wxc_common/src/filesystem_access.rs | Implements the delegation check and associated unit tests. |
| src/backends/wslc/common/src/wsl_container_runner.rs | Runs delegation check early in WSLC runner to reject inaccessible policy paths. |
| src/backends/lxc/common/src/lxc_runner.rs | Runs delegation check at start of LXC execution path. |
| src/backends/bubblewrap/common/src/bwrap_runner.rs | Runs delegation check before spawning bwrap. |
3381a65 to
e1623d1
Compare
| Some(true) | ||
| } | ||
| _ => { | ||
| // Only an explicit access denial is a delegation failure. Any other |
There was a problem hiding this comment.
Copilot tells me - Unix uses a skip-list (only genuine "missing" is skipped; the default is reject). Windows uses a reject-list (only explicit access-denied is rejected; the default is skip). A ERROR_SHARING_VIOLATION, ERROR_LOCK_VIOLATION, or transient IO error on a real, existing file hits the Windows default and is silently skipped — the exact opposite of what the same situation does on Unix.
So on Unix "non-existent is surfaced separately" is achieved by listing the missing errnos and rejecting everything else; on Windows the author achieves it by skipping everything except one error. Those are not the same posture.
There was a problem hiding this comment.
Thanks for the catch, seems to be a valid concern, will address.
The delegation access-probe used asymmetric error handling across platforms: Unix skipped only genuine-missing paths and rejected everything else (fail-closed), while Windows rejected only ERROR_ACCESS_DENIED and skipped every other failure (fail-open). A sharing/lock violation or transient I/O error on a real, existing file was therefore silently allowed on Windows but rejected on Unix — the opposite posture for a security delegation gate. Align Windows to the Unix posture: skip only ERROR_FILE_NOT_FOUND / ERROR_PATH_NOT_FOUND (surfaced separately by the existence warning); treat every other failure, including access-denied and ambiguous errors, as 'cannot confirm access' and reject. Add a Windows test locking the fail-closed behavior for an ambiguous (ERROR_INVALID_NAME) error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📖 Description
Enforce that the container is never granted more filesystem access than the invoking user already holds: every readwritePaths entry requires the user to have read+write access, and every readonlyPaths entry requires read access. deniedPaths are unbounded (denying needs no access) and are not checked. A path the user cannot access is rejected, so a sandboxed process can't reach files the caller themselves couldn't.
🔗 References
🔍 Validation
✅ Checklist
📋 Issue Type
GitHub Actions runs the PR validation build automatically. The ADO pipeline
(
MXC-PR-Build) is the official build pipeline that signs the binaries; itruns on merge to
mainand nightly, and Microsoft reviewers can trigger iton a PR with
/azp run. See docs/pull-requests.md.Microsoft Reviewers: Open in CodeFlow